#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Module辅助工具
为Module文件提供便捷的API
"""

import os
import logging
from pathlib import Path
from typing import List, Optional, Union
from target_registry import BuildTarget, TargetType, TargetRegistry
from build_manager import BuildManager

class ModuleHelper:
    """Module辅助类"""

    def __init__(self, env, build_manager: BuildManager, target_registry: TargetRegistry, module_dir: str):
        """
        初始化Module辅助类

        Args:
            env: SCons环境
            build_manager: 构建管理器
            target_registry: 目标注册表
            module_dir: Module所在目录
        """
        self.env = env
        self.build_manager = build_manager
        self.target_registry = target_registry
        self.module_dir = os.path.abspath(module_dir)
        self.module_name = os.path.basename(self.module_dir)

    def add_executable(self, name: str, sources: List[str], **kwargs) -> BuildTarget:
        """
        添加可执行文件目标

        Args:
            name: 目标名称
            sources: 源文件列表
            **kwargs: 其他选项

        Returns:
            构建目标
        """
        logging.info(f"ModuleHelper.add_executable called for {name} with kwargs: {kwargs}")
        return self._add_target(name, TargetType.EXECUTABLE, sources, **kwargs)

    def add_shared_library(self, name: str, sources: List[str], **kwargs) -> BuildTarget:
        """
        添加动态库目标

        Args:
            name: 目标名称
            sources: 源文件列表
            **kwargs: 其他选项

        Returns:
            构建目标
        """
        return self._add_target(name, TargetType.SHARED_LIBRARY, sources, **kwargs)

    def add_static_library(self, name: str, sources: List[str], **kwargs) -> BuildTarget:
        """
        添加静态库目标

        Args:
            name: 目标名称
            sources: 源文件列表
            **kwargs: 其他选项

        Returns:
            构建目标
        """
        return self._add_target(name, TargetType.STATIC_LIBRARY, sources, **kwargs)

    def add_object_files(self, name: str, sources: List[str], **kwargs) -> BuildTarget:
        """
        添加目标文件

        Args:
            name: 目标名称
            sources: 源文件列表
            **kwargs: 其他选项

        Returns:
            构建目标
        """
        return self._add_target(name, TargetType.OBJECT_FILES, sources, **kwargs)

    def add_header_library(self, name: str, **kwargs) -> BuildTarget:
        """
        添加头文件库目标

        Args:
            name: 目标名称
            **kwargs: 其他选项（如export_include_paths等）

        Returns:
            构建目标
        """
        return self._add_target(name, TargetType.HEADER_LIBRARY, [], **kwargs)

    def add_proto_library(self, name: str, proto_files: List[str], **kwargs) -> BuildTarget:
        """
        添加Protocol Buffers库目标

        Args:
            name: 目标名称
            proto_files: proto文件列表
            **kwargs: 其他选项
                proto_type: proto类型 (full/lite/min)，默认为full
                proto_path: proto文件搜索路径
                export_include_paths: 导出的头文件路径

        Returns:
            构建目标
        """
        return self._add_target(name, TargetType.PROTO_LIBRARY, proto_files, **kwargs)

    def _add_target(self, name: str, target_type: TargetType, sources: List[str], **kwargs) -> BuildTarget:
        """
        添加编译目标

        Args:
            name: 目标名称
            target_type: 目标类型
            sources: 源文件列表
            **kwargs: 其他选项

        Returns:
            构建目标
        """
        # 处理源文件路径
        processed_sources = self._process_source_paths(sources)

        # 创建目标
        target = BuildTarget(name, target_type, processed_sources, self.module_dir)

        # 设置选项
        self._apply_target_options(target, **kwargs)

        # 注册目标
        self.target_registry.register_target(target)

        return target

    def _process_source_paths(self, sources: List[str]) -> List[str]:
        """
        处理源文件路径

        Args:
            sources: 源文件列表

        Returns:
            处理后的源文件路径列表
        """
        processed = []

        for source in sources:
            if os.path.isabs(source):
                # 绝对路径直接使用
                processed.append(source)
            else:
                # 相对路径相对于Module目录
                abs_path = os.path.join(self.module_dir, source)
                processed.append(abs_path)

        return processed

    def _apply_target_options(self, target: BuildTarget, **kwargs):
        """
        应用目标选项

        Args:
            target: 编译目标
            **kwargs: 选项字典
        """
        # 依赖项
        if 'depends' in kwargs:
            depends = kwargs['depends']
            if isinstance(depends, str):
                target.add_dependency(depends)
            elif isinstance(depends, list):
                for dep in depends:
                    target.add_dependency(dep)

        # 依赖项（另一种参数名）
        if 'dependencies' in kwargs:
            dependencies = kwargs['dependencies']
            if isinstance(dependencies, str):
                target.add_dependency(dependencies)
            elif isinstance(dependencies, list):
                for dep in dependencies:
                    target.add_dependency(dep)


        # 动态库
        if 'shared_libs' in kwargs:
            shared_libs = kwargs['shared_libs']
            if isinstance(shared_libs, str):
                target.add_shared_lib(shared_libs)
                target.add_dependency(shared_libs)  # 自动添加依赖关系
            elif isinstance(shared_libs, list):
                for lib in shared_libs:
                    target.add_shared_lib(lib)
                    target.add_dependency(lib)  # 自动添加依赖关系

        # 静态库
        if 'static_libs' in kwargs:
            static_libs = kwargs['static_libs']
            if isinstance(static_libs, str):
                target.add_static_lib(static_libs)
                target.add_dependency(static_libs)  # 自动添加依赖关系
            elif isinstance(static_libs, list):
                for lib in static_libs:
                    target.add_static_lib(lib)
                    target.add_dependency(lib)  # 自动添加依赖关系

        # 头文件库
        if 'header_libs' in kwargs:
            header_libs = kwargs['header_libs']
            logging.info(f"Processing header_libs for {target.name}: {header_libs}")
            if isinstance(header_libs, str):
                target.add_dependency(header_libs)
                logging.info(f"Added header_lib dependency: {header_libs}")
            elif isinstance(header_libs, list):
                for lib in header_libs:
                    target.add_dependency(lib)
                    logging.info(f"Added header_lib dependency: {lib}")

        # 库搜索路径
        if 'lib_paths' in kwargs:
            lib_paths = kwargs['lib_paths']
            if isinstance(lib_paths, str):
                target.add_lib_path(self._resolve_path(lib_paths))
            elif isinstance(lib_paths, list):
                for path in lib_paths:
                    target.add_lib_path(self._resolve_path(path))

        # 头文件搜索路径
        if 'include_paths' in kwargs:
            include_paths = kwargs['include_paths']
            if isinstance(include_paths, str):
                target.add_include_path(self._resolve_path(include_paths))
            elif isinstance(include_paths, list):
                for path in include_paths:
                    target.add_include_path(self._resolve_path(path))

        # 导出的头文件搜索路径
        if 'export_include_paths' in kwargs:
            export_include_paths = kwargs['export_include_paths']
            if isinstance(export_include_paths, str):
                target.add_export_include_path(self._resolve_path(export_include_paths))
            elif isinstance(export_include_paths, list):
                for path in export_include_paths:
                    target.add_export_include_path(self._resolve_path(path))

        # 预处理宏定义
        if 'defines' in kwargs:
            defines = kwargs['defines']
            if isinstance(defines, str):
                target.add_define(defines)
            elif isinstance(defines, list):
                for define in defines:
                    target.add_define(define)

        # 编译选项
        if 'cflags' in kwargs:
            target.cflags.extend(self._ensure_list(kwargs['cflags']))

        if 'cxxflags' in kwargs:
            target.cxxflags.extend(self._ensure_list(kwargs['cxxflags']))

        if 'ldflags' in kwargs:
            target.ldflags.extend(self._ensure_list(kwargs['ldflags']))

        # 输出目录
        if 'output_dir' in kwargs:
            target.output_dir = self._resolve_path(kwargs['output_dir'])

        # 安装目录
        if 'install_dir' in kwargs:
            target.install_dir = self._resolve_path(kwargs['install_dir'])

        # 处理Proto相关选项
        if target.target_type == TargetType.PROTO_LIBRARY:
            # 处理proto文件列表
            proto_files = kwargs.get('proto_files', target.sources)
            if proto_files:
                target.proto_files = [self._resolve_path(f) for f in self._ensure_list(proto_files)]

            # 处理proto类型
            proto_type = kwargs.get('proto_type', 'full')
            if proto_type in ['full', 'lite', 'min']:
                target.proto_type = proto_type
            else:
                logging.warning(f"Invalid proto_type '{proto_type}', using 'full'")
                target.proto_type = 'full'

            # 处理proto搜索路径
            proto_path = kwargs.get('proto_path')
            if proto_path:
                if isinstance(proto_path, list):
                    # 如果是列表，取第一个路径作为主要搜索路径
                    target.proto_path = self._resolve_path(proto_path[0]) if proto_path else self.module_dir
                else:
                    target.proto_path = self._resolve_path(proto_path)
            else:
                # 默认使用Module目录作为proto搜索路径
                target.proto_path = self.module_dir

    def _resolve_path(self, path: str) -> str:
        """
        解析路径

        Args:
            path: 路径字符串

        Returns:
            解析后的绝对路径
        """
        if os.path.isabs(path):
            return path
        else:
            return os.path.join(self.module_dir, path)

    def _ensure_list(self, value: Union[str, List[str]]) -> List[str]:
        """
        确保值为列表

        Args:
            value: 字符串或列表

        Returns:
            列表
        """
        if isinstance(value, str):
            return [value]
        elif isinstance(value, list):
            return value
        else:
            return []

    def glob_sources(self, pattern: str) -> List[str]:
        """
        使用glob模式匹配源文件

        Args:
            pattern: glob模式

        Returns:
            匹配的文件列表
        """
        import glob

        if os.path.isabs(pattern):
            search_pattern = pattern
        else:
            search_pattern = os.path.join(self.module_dir, pattern)

        return glob.glob(search_pattern)

    def get_module_dir(self) -> str:
        """
        获取Module目录

        Returns:
            Module目录路径
        """
        return self.module_dir

    def get_module_name(self) -> str:
        """
        获取Module名称

        Returns:
            Module名称
        """
        return self.module_name

# 全局辅助函数
def create_module_helper(env, build_manager: BuildManager, target_registry: TargetRegistry, module_path: str) -> ModuleHelper:
    """
    创建Module辅助对象

    Args:
        env: SCons环境
        build_manager: 构建管理器
        target_registry: 目标注册表
        module_path: Module文件路径

    Returns:
        Module辅助对象
    """
    module_dir = os.path.dirname(module_path)
    return ModuleHelper(env, build_manager, target_registry, module_dir)